# -*- coding:utf-8 -*-
import hmac
import base64
import struct
import hashlib
import time
import os
import subprocess
import datetime
import random
import string

# 全局变量定义
old_password = ''  # 旧密码
username = ''  # 用户名
pwd_key = ''  # 口令指定后缀
secret = ''

def get_hotp_token(secret, intervals_no):
    """
    生成基于HOTP算法的一次性密码

    :param secret: 秘钥
    :param intervals_no: 时间间隔
    :return: 6位数字字符串的一次性密码
    """
    key = base64.b32decode(secret, True)
    msg = struct.pack(">Q", intervals_no)
    h = hmac.new(key, msg, hashlib.sha1).digest()
    o = h[19] & 15  # 使用位操作，无需 ord() 和 chr()
    h = (struct.unpack(">I", h[o:o + 4])[0] & 0x7fffffff) % 1000000
    return '{:06d}'.format(h)

def get_totp_token(secret):
    """
    生成基于TOTP算法的一次性密码

    :param secret: 秘钥
    :return: 6位数字字符串的一次性密码
    """
    return get_hotp_token(secret, intervals_no=int(time.time()) // 30)

def log_info(data):
    """
    将错误日志记录到文件中

    :param data: 要记录的日志信息
    """
    current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    log_entry = f"{current_time} - {data}\n"

    try:
        with open('run_error_log.txt', 'r', encoding='utf-8') as file:
            existing_logs = file.read()
        if data in existing_logs:
            return  # 日志已经存在，不进行写入
    except FileNotFoundError:
        pass

    with open('run_error_log.txt', 'a', encoding='utf-8') as file:
        file.write(log_entry)

def change_password(username, new_password):
    """
    更改用户密码

    :param username: 用户名
    :param new_password: 新密码
    """
    global old_password, pwd_key

    cmd = f'net user {username} {new_password}'
    result = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                            creationflags=subprocess.CREATE_NO_WINDOW)
    if result.returncode == 0:
        old_password = new_password
    else:
        log_info(f"密码修改失败，旧密码：{old_password}\n{pwd_key}")

def main_loop():
    """
    主循环，持续检查并更新用户密码
    """
    global old_password, username, secret, pwd_key

    while True:
        new_password = get_totp_token(secret)  # 设置一个自己的secret
        complete_new_password = new_password + pwd_key  # 添加后缀以避免纯数字密码
        if complete_new_password != old_password:
            change_password(username, complete_new_password)  # 执行修改密码
        time.sleep(1)

def get_user():
    """
    获取当前运行程序的用户名

    :return: 用户名
    """
    global username

    try:
        username = os.getlogin()
    except Exception as e:
        log_info(f"os.getlogin() 方法失败：{e}")
        try:
            username = os.environ['USERNAME']
        except KeyError as e:
            log_info(f"os.environ['USERNAME'] 方法失败：{e}")
            username = None

    log_info(f"当前登录的用户名：{username}")
    return username

def generate_secret():
    """
    生成新的随机秘钥

    :return: 16位大写字母组成的字符串
    """
    letters = string.ascii_uppercase
    return ''.join(random.choice(letters) for _ in range(16))


def read_config(file_name='config.ini'):
    """
    读取配置文件中的用户名和秘钥

    :param file_name: 配置文件名
    :return: 用户名, 秘钥, 密钥后缀
    """
    global username, secret, pwd_key
    try:
        with open(file_name, 'r', encoding='utf-8') as file:
            lines = file.readlines()
            username = lines[0].strip() if len(lines) >= 1 else ''
            secret = lines[1].strip() if len(lines) >= 2 else ''
            pwd_key = lines[2].strip() if len(lines) >= 3 else ''

            # 检查secret是否合规
            if not is_valid_secret(secret):
                secret = ''

            return username, secret, pwd_key
    except FileNotFoundError:
        return None, None, None

def is_valid_secret(secret):
    """
    检查秘钥是否是16位大写字母

    :param secret: 要检查的秘钥
    :return: 是否有效的布尔值
    """
    if len(secret) == 16 and all(char in string.ascii_uppercase for char in secret):
        return True
    log_info(f"{secret}  秘钥格式不正确，应为16位大写字母")
    return False

def check_config():
    """
    检查配置文件是否存在，如果不存在则创建新配置文件
    """
    global username, secret, pwd_key
    if not os.path.exists('config.ini'):
        username = get_user()
        secret = generate_secret()
        with open('config.ini', 'w', encoding='utf-8') as file:
            file.write(f"{username}\n{secret}\n{pwd_key}\n")
    else:
        read_config()
        log_info(f'\n账号名：{username}\nsecret：{secret}\n态密钥后缀：{pwd_key}\n')

if __name__ == "__main__":
    check_config()
    main_loop()  # 运行主循环
